//
//  SqlManager.swift
//  TuneMate
//
//  Created by 丸子 on 2023/11/23.
//
 
import Foundation
// 定义表名协议，用于获取表名
public protocol TableNamed {
    static var tableName: String { get }
}
// 定义数据表需要遵守的协议组合
public typealias TableObject = TableNamed & HandyJSON & TableCodable
// 定义数据库管理类
class SqlManager {
    static let shared = SqlManager() // 单例对象
    private let database: Database // 数据库对象
    private let debugPrefix: (success: String, failure: String) = (success: "Sqlite Success", failure: "Sqlite Failure") // 调试前缀常量
    private init() {
        let documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .allDomainsMask, true).first?.appendingPathComponent("NDAi.db") ?? "" // 获取数据库文件路径
        database = Database(withPath: documentPath)
    }
    func create<Table: TableObject>(_ table: Table.Type) {
        do {
            try database.run(transaction:  {
                try self.database.create(table: table.tableName, of: table)
            })
        } catch {}
    }
    func insert<Table: TableObject>(_ objects: [Table]) {
        try? database.insertOrReplace(objects: objects, intoTable: Table.tableName)
    }

    func delete<Table: TableObject>(from tableType: Table.Type, where condition: Condition? = nil) {
        do {
            try database.run(transaction:  {
                try database.delete(fromTable: Table.tableName, where: condition)
            })
        } catch {}
    }
    func update<Table: TableObject>(on properties: [PropertyConvertible], with object: Table, where condition: Condition) {
        do {
            try database.run(transaction:  {
                try database.update(table: Table.tableName, on: properties, with: object, where: condition)
            })
        } catch {
            XLog.d(debugPrefix.failure, "Table[\(Table.tableName)] Update Error: \(error.localizedDescription)")
        }
    }
    func filter<Table: TableObject>(from tableType: Table.Type, where condition: Condition? = nil, limit: Limit? = nil, offset: Offset? = nil) -> [Table]? {
        var objects: [Table]?
        do {
            objects = try database.getObjects(on: tableType.Properties.all, fromTable: Table.tableName, where: condition, limit: limit, offset: offset)
            objects = objects?.reversed() // 反转对象数组
        } catch {}
        return objects // 返回对象数组
    }
    
    func exist<Table: TableObject>(where condition: Condition, from tableType: Table.Type) -> Bool {
        let objects = self.filter(from: tableType, where: condition)
        return objects?.count ?? 0 >= 1
    }
}
